package cz.proks.easyhelpdesk.gwt.ui.widget;

import java.util.Arrays;
import java.util.Collection;
import java.util.Date;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.shared.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DateLabel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

import cz.proks.easyhelpdesk.api.model.Category;
import cz.proks.easyhelpdesk.api.model.Ticket;
import cz.proks.easyhelpdesk.gwt.HelpdeskMessages;
import cz.proks.easyhelpdesk.gwt.event.CancelEvent;
import cz.proks.easyhelpdesk.gwt.event.CancelEvent.Handler;
import cz.proks.easyhelpdesk.gwt.event.HasCancelHandlers;
import cz.proks.easyhelpdesk.gwt.event.HasTicketReplyHandlers;
import cz.proks.easyhelpdesk.gwt.event.HasTicketSaveHandlers;
import cz.proks.easyhelpdesk.gwt.event.TicketReplyEvent;
import cz.proks.easyhelpdesk.gwt.event.TicketSaveEvent;

public class TicketWidget extends Composite implements RequiresErase, HasTicketSaveHandlers, HasTicketReplyHandlers, HasCancelHandlers {

    private static TicketWidgetUiBinder uiBinder = GWT.create(TicketWidgetUiBinder.class);

    interface TicketWidgetUiBinder extends UiBinder<Widget, TicketWidget> {
    }
    
    public enum Mode {NEW, FIRST_VIEW, VIEW, LAST_VIEW, ONE_ONLY_VIEW, REPLY}

    private Mode mode; 

    @UiField HelpdeskMessages i18n;
    
    @UiField(provided=true) H3Widget header = new H3Widget().withNoTopMargin();
    
    @UiField FlowPanel topButtonsPanel;
    @UiField FlowPanel bottomButtonsPanel;
    
    @UiField SaveButton saveButton;
    @UiField ReplyButton replyButton;    
    @UiField CancelButton cancelButton;    
    
    @UiField FlowPanel ticketInfoPanel; 
    @UiField Label nameLabel;
    @UiField(provided=true) DateLabel createdLabel = new DateLabel(DateTimeFormat.getFormat("HH:mm dd.MM.yyyy"));
    
    @UiField FlowPanel categoryRow;
    @UiField ListBox categoryListBox;
    @UiField Label categoryLabel;
    
    @UiField FlowPanel subjectRow;
    @UiField TextBox subjectBox;
    @UiField Label subjectLabel;
    
    @UiField FlowPanel descriptionRow;    
    @UiField Label descriptionLabel;
    @UiField FlowPanel descriptionRichTextContainer;    
    @UiField HTMLPanel descriptionHtmlArea;             
    @UiField DashedPanel dashedPanel;
    
    
    private RichTextArea descriptionRichTextArea = new RichTextArea();
    private RichTextToolbar descriptionRichTextToolbar = new RichTextToolbar(descriptionRichTextArea);   
    
    @UiConstructor
    public TicketWidget(Mode mode) {
        this.mode = mode;
        
        this.descriptionRichTextToolbar.setWidth("100%");
        this.descriptionRichTextArea.setWidth("100%");
        
        initWidget(uiBinder.createAndBindUi(this));                
        
        this.descriptionRichTextContainer.clear();
        this.descriptionRichTextContainer.add(descriptionRichTextToolbar);
        this.descriptionRichTextContainer.add(descriptionRichTextArea);
        
        this.createdLabel.setValue(new Date());
        this.nameLabel.setText("Full username");                         
    }        
    
    @Override
    protected void initWidget(Widget widget) {     
        super.initWidget(widget);
        setPanelsVisibility();      
    }  
    
    @Override
    public HandlerRegistration addTicketSaveHandler(TicketSaveEvent.Handler handler) {
        return addHandler(handler, TicketSaveEvent.TYPE);
    }
    
    @Override
    public HandlerRegistration addTicketReplyHandler(TicketReplyEvent.Handler handler) {
        return addHandler(handler, TicketReplyEvent.TYPE);
    }        
            
    @Override
    public HandlerRegistration addCancelHandler(Handler handler) {
        return addHandler(handler, CancelEvent.TYPE);
    }
    
    @Override
    public void onErase() {
        subjectBox.setText("");
        
        descriptionHtmlArea.clear();
        descriptionRichTextArea.setText("");
        
        categoryListBox.setSelectedIndex(categoryListBox.getItemCount() > 0 ? 0 : -1);
    }

    public void setMode(Mode mode) {
        this.mode = mode;
        setPanelsVisibility();
    }
    
    public Mode getMode() {
        return mode;
    }
    
    public void setUsernameLabel(String name) {
        this.nameLabel.setText(name);
    }
    
    public void setCreatedDate(Date date) {
        this.createdLabel.setValue(date);
    }    
    
    public void setCategories(Category... categories) {
        Collection<Category> catagoryCollection = Arrays.asList(categories);
        setCategories(catagoryCollection);
    }
    
    public void setCategories(Collection<Category> categories) {        
        categoryListBox.clear();
        categoryLabel.setText(null);
        
        if (categories != null && !categories.isEmpty()) {
            for (Category category : categories)
                categoryListBox.addItem(category.getLabel(), String.valueOf(category.getId()));
            
            categoryListBox.setSelectedIndex(0);
            categoryLabel.setText(categoryListBox.getItemText(0));
        }
    }    
    
    public Long getCategoryId() {
        int selected = categoryListBox.getSelectedIndex();
        return selected != -1 ? Long.valueOf(categoryListBox.getValue(selected)) : -1l;
    }
    
    public String getCategoryLabel() {
        int selected = categoryListBox.getSelectedIndex();
        return selected != -1 ? categoryListBox.getItemText(selected) : null;
    }
    
    public String getSubject() {
        return subjectBox.getText();
    }
    
    public void setSubject(String subject) {
        this.subjectBox.setText(subject);        
        this.subjectLabel.setText(subject);
        
        if (mode == Mode.FIRST_VIEW || mode == Mode.ONE_ONLY_VIEW)
            this.header.setText(subject);
        else
            this.header.setText(i18n.ticketNew());
    }
    
    public String getDescription() {
        return descriptionRichTextArea.getHTML();
    }
    
    public void setDescription(String html) {        
        descriptionRichTextArea.setHTML(html);
        
        descriptionHtmlArea.clear();
        descriptionHtmlArea.add(new HTML(html));
    }
    
    private void setPanelsVisibility() {
        switch (mode) {
            case NEW:               
                header.setVisible(true);
                
                topButtonsPanel.setVisible(true);               
                bottomButtonsPanel.setVisible(false);
                ticketInfoPanel.setVisible(false);                                                
                
                categoryRow.setVisible(true);
                categoryListBox.setVisible(true);
                categoryLabel.setVisible(false);
                
                subjectRow.setVisible(true);
                subjectBox.setVisible(true);
                subjectLabel.setVisible(false);
                
                descriptionRow.setVisible(true);
                descriptionLabel.setVisible(true);
                descriptionRichTextContainer.setVisible(true);
                descriptionHtmlArea.setVisible(false);
                dashedPanel.setVisible(false);
                break;            
            
            case FIRST_VIEW:
            case LAST_VIEW:
            case VIEW:
            case ONE_ONLY_VIEW:
                header.setVisible(mode == Mode.FIRST_VIEW || mode == Mode.ONE_ONLY_VIEW);
                
                topButtonsPanel.setVisible(false);                                
                bottomButtonsPanel.setVisible(mode == Mode.LAST_VIEW || mode == Mode.ONE_ONLY_VIEW);
                ticketInfoPanel.setVisible(true);
                
                categoryRow.setVisible(false);
                categoryListBox.setVisible(false);
                categoryLabel.setVisible(true);
                
                subjectRow.setVisible(false);
                subjectBox.setVisible(false);
                subjectLabel.setVisible(false);
                
                descriptionRow.setVisible(true);
                descriptionLabel.setVisible(false);
                descriptionRichTextContainer.setVisible(false);
                descriptionHtmlArea.setVisible(true);
                dashedPanel.setVisible(mode == Mode.FIRST_VIEW || mode == Mode.VIEW);
                break;
                
            case REPLY:
                header.setVisible(false);
                topButtonsPanel.setVisible(true);                
                bottomButtonsPanel.setVisible(false);
                ticketInfoPanel.setVisible(false);
                
                categoryRow.setVisible(true);
                categoryListBox.setVisible(false);
                categoryLabel.setVisible(true);
                
                subjectRow.setVisible(true);
                subjectBox.setVisible(false);
                subjectLabel.setVisible(true);
                
                descriptionRow.setVisible(true);
                descriptionLabel.setVisible(true);
                descriptionRichTextContainer.setVisible(true);
                descriptionHtmlArea.setVisible(false);
                dashedPanel.setVisible(false);
                break;            
        }
    }
    
    private Ticket getTicket() {
        Ticket ticket = new Ticket();
        
        ticket.setCategoryId(getCategoryId());
        ticket.setSubject(getSubject());
        ticket.setDescription(getDescription());
        
        return ticket;
    }
    
    @UiHandler("saveButton")
    void onSaveButtonClick(ClickEvent event) {
        event.preventDefault();
        TicketSaveEvent.fireEvent(this, getTicket());
    }
    
    @UiHandler("replyButton")
    void onReplyButtonClick(ClickEvent event) {
        event.preventDefault();
        TicketReplyEvent.fireEvent(this, getTicket());
    }     
    
        
    @UiHandler("cancelButton")
    void onCancelButtonClick(ClickEvent event) {
        event.preventDefault();
        CancelEvent.fireEvent(this);               
    }
}
